rm(list = ls())
setwd("C:\\Users\\lenovo\\Desktop\\R")
#3.1 用基本包处理数据框
#install.packages("epiDisplay")
#install.packages("nnet")
library(epiDisplay)
data(Familydata)
ls()

#3.1.1 查看数据框里的内容
Familydata
head(Familydata, 3)#查看前三行的数据,默认显示6行
tail(Familydata, 3)#查看后三行的数据，默认显示6行
names(Familydata)#使用函数names查看变量名
str(Familydata)#查看对象的类型、建立因子水平、查看变量的类型
attr(Familydata, "var.labels")[1] <- "Identification number"
attr(Familydata, "var.labels")[6] <- "Gender"
attributes(Familydata)$var.labels
des(Familydata)#epiDisplay包

#3.1.2 选取数据框的子集
Familydata[,3]
Familydata$ht  #上下等价
Familydata[1:3, c(3,4,6)]
Familydata[1:3, c("ht","wt","sex")]
Familydata[Familydata$sex = "F",]
#条件表达式后面跟一个逗号，表示选择所有的列
subset(Familydata, sex == "F", select = c(ht, wt))
#机器学习领域中用于抽取样本：
#抽取一个大小为3的样本
sample.rows<- sample(1: nrow(Familydata),
                     #由要从中抽样的元素构成的向量
                     size = 3,#抽取元素的数量
                     replace = FALSE)#默认为不放回抽样
sample.rows
Familydata[sample.rows,]

#3.1.3 将数据框按照某个变量的值排序
Familydata[order(Familydata$age),]#从小到大
Familydata[order(Familydata$age, decreasing = TRUE)]#从大到小
Familydata[order(-Familydata$age),]#从大到小

#3.1.4 查找和删除重复数据
#查找某一变量是否有重复值
duplicated(Familydata$code)
#如果有TRUE，返回TRUE；否则，FALSE
any(duplicated(Familydata$code))
#查看有几个FALSE
table(duplicated(Familydata$code))
#将原数据框Familydata的第2行添加在第12行
Familydata1 <- Familydata
Familydata1[12, ] <- Familydata[2, ]
Familydata1
table(duplicated(Familydata1$code))
#找出变量code的重复值所在的行
which(duplicated(Familydata1$code))
#删除重复的行
unique.code.data <- Familydata1[!duplicated(Familydata1$code),]
#别忘了逗号!!!!!!
identical(unique.code.data, Familydata)

#3.1.5 在数据框中添加和删除变量
Familydata$log10money <- log10(Familydata$money)
Familydata <-transform(Familydata, log10money = log10(money))
names(Familydata)
#删除一个变量，但其实只是显示子集，对原数据集不影响
Familydata[,-7]
Familydata$money <- NULL#永久删除一个变量
#3.1.6 把数据框添加到搜素路径
attach(Familydata)#将数据集放入全局变量中
search()
summary(age)
#用一次数据，用一次with；赋值仅在函数内生效
with(infert, summary(age))
#不用的数据框从搜索路径中删除
detach(Familydata)
search()

#3.2 用dplyr包处理数据框
library(dplyr)
data(birthwt, package = "MASS")
?birthwt
#3.2.1 使用filter、slice筛选行
filter(birthwt, age > 35)
filter(birthwt, bwt < 2500 | bwt > 3500)
filter(birthwt, age > 35, bwt < 2500 | bwt > 3500)
#选择数据集里第2行到第5行
slice(birthwt, 2:5)
#3.2.2 使用arrange排列行
#从小到大
arrange(birthwt, bwt)
arrange(birthwt, bwt, age)
#从大到小
arrange(birthwt, desc(bwt))
arrange(birthwt, -bwt)
#3.2.3 使用select选择行
#指定dplyr包的函数select
dplyr::select(birthwt, bwt, age, race, smoke)
#3.2.4 使用mutate添加新变量
mutate(birthwt, lwt.kg = lwt * 0.4536)
#用新变量替换原变量
mutate(birthwt, lwt = 0.4536)
#3.2.5 使用summarise计算统计量
summarise(birthwt, Mean.bwt = mean(bwt), Sd.bwt = sd(bwt))
#3.2.6 使用group_by拆分数据框
group_by(birthwt, race)
as_tibble(birthwt)
#3.2.7 使用传递符“%>%”组合多个条件
#将变量race转换为因子，并给每个水平添加标签
birthwt1 <- mutate(birthwt,
                   race = factor(race,
                   labels =c("white", "black", "other")))
#按照变量分组
birthwt.group <- group_by(birthwt1, race)
#计算各组中bwt的平均值
summarise(birthwt.group, mean(bwt))
#简单示范，如何传递
#%>%将符号前的对象传给后面的函数，并作为第一个参数
c(2,4,6,8) %>% matrix(nrow = 2)
birthwt %>%
  mutate(race = factor(race,labels =c("white", "black", "other"))) %>%
  group_by(race) %>%
  summarise(mean(bwt))
#3.3 数据框的合并
#3.3.1 纵向合并
data1 <- data.frame(id = 1:5,
                    sex = c("female", "male", "male","female","male"),
                    age = c(32, 46, 25, 42, 29))
data1
data2 <- data.frame(id = 6:10,
                    age = c(52, 36, 28, 34, 26),
                    sex = c("male", "female","male","male","female")
                    )
data2
#rbind是按照变量名合并，无须担心顺序
rbind(data1, data2)
#3.3.2 横向合并
data3 <- data.frame(days = c(28,57,15,7,19),
outcome = c("disacharge", "dead", "discharge","transfer","discharge"))
data3
cbind(data1,data3)
#3.3.3 按照某个共有变量合并
data1
data4 <- data.frame(id = c(1, 2 , 3 , 4 ,5),
outcome = c("discharge", "dead", "discharge","transfer","discharge"))
data4
mydata <- merge(data1, data4, by = "id")
mydata
library(dplyr)
mydata <- full_join(data1, data4, by = "id")
mydata
#3.4 数据框的长宽格式的转换
data(Indometh)
Indometh
wide <- reshape(Indometh,
                v.names = "conc",
                idvar = "Subject",
                timevar = "time",
                direction = "wide")
wide
long <- reshape(wide, 
                idvar = "Subject",
                varying = list(2:12),
                v.names = "conc",
                direction = "long")
head(long, 12)

library(tidyr)
wide <- pivot_wider(as.data.frame(Indometh),
                    names_from = time,
                    values_from = conc)
wide
long <- pivot_longer(wide, 
                     -Subject,
                     names_to = "time",
                     values_to = "conc")
long

#3.5 缺失值的处理
#3.5.1 识别缺失值
height <- c(100, 50, NA, 160)
height
is.na(height)
table(is.na(height))
#包含NA的计算结果为NA
mean(height)
mean(height, na.rm = TRUE)
mean(na.omit(height))
summary(height)
#3.5.2 探索数据框里的缺失值
#install.packages("missForest")
library(missForest)
set.seed(1234)
#随机生成缺失值
iris.miss <- prodNA(iris)
summary(iris.miss)
#用VIM包来可视化缺失值
#install.packages("VIM")
library(VIM)
aggr(iris.miss, prop = FALSE, numbers = TRUE, cex.axis = 0.7)
#3.5.3 填充缺失值
#1.删除
iris.sub <- na.omit(iris.miss)
nrow(iris.sub)
iris.sub <- iris.miss[complete.cases(iris.miss), ]
#2. 使用特定数值替换缺失值
#用忽略缺失值后的均值替换该变量里的缺失值
Sepal.Length.Mean <- mean(iris.miss$Sepal.Length, na.rm = TRUE)
Sepal.Length.Mean
#将缺失值用算得的均值替换
iris.miss1 <- iris.miss
iris.miss1$Sepal.Length[is.na(iris.miss1$Sepal.Length)] <- Sepal.Length.Mean
#检查补全后的数据与原始数据的差异
summary((iris$Sepal.Length - iris.miss1$Sepal.Length)/iris$Sepal.Length)
#3. 多重插补
#mice包假设数据是随机缺失的，并根据变量的类型建立模型得到预测值
#install.packages("mice")
library(mice)
imputed.data <- mice(iris.miss, seed = 1234)
summary(imputed.data)
#得到变量Sepal.Length的插补值,默认有5组插补值
imputed.data$imp$Sepal.Length
#取5组插补值中的第3个
complete.data <- complete(imputed.data, 3)
#检查插补值的补全效果
#数值型变量的检查
summary((iris$Sepal.Length - complete.data$Sepal.Length)/iris$Sepal.Length)
#因子的检查
table(iris$Species,complete.data$Species)

#3.6 处理大型数据集的策略
#3.6.1 清理工作空间
rm(list = ls(all = TRUE))
#3.6.2 快速读取.csv文件
library(readr)
read_csv()
#更快的读取速度。适用于1-10GB的大数据
library(data.table)
read.fread()
#3.6.3 模拟一个大型数据库
bigdata <- as.data.frame(matrix(rnorm(50000 * 200), ncol = 200))
varnames <- NULL
for (i in letters[1:20]) {
  for (j in 1:10) {
    varnames <- c(varnames,paste(i, j, sep = "_"))
  }
}
names(bigdata) <- varnames
names(bigdata)
#3.6.4 剔除不需要的变量
library(dplyr)
library(tidyselect)
#dplyr的select与tidyselect的starts_with, ends_with, contain
subdata1 <- select(bigdata, starts_with("a"))
names(subdata1)
subdata2 <- select(bigdata, ends_with("2"))
names(subdata2)
#选取所有以“a”或“b”开头的变量
subdata3 <- select_at(bigdata, 
                      vars(starts_with("a"),
                           starts_with("b")))
names(subdata3)
#选择变量名中包含某些字符的所有变量
subdata4 <- select_at(bigdata, vars(contains("1")))
names(subdata4)
#剔除以"1"或“5”结尾的变量
subdata5 <- select_at(bigdata, 
                      vars(-ends_with("1"), -ends_with("5"))
                      )
#3.6.5 选取数据集的一个随机样本
#指定行的个数
sampledata1 <- sample_n(subdata5, size = 500)
nrow(sampledata1)
#指定行的比例
sampledata2 <- sample_frac(subdata5, size = 0.02)
nrow(sampledata2)

rm(list = ls(all = TRUE))

#习题
